// ZobristTable.cpp

#include "includes.h"

ZobristTable::ZobristTable()
{
	FILE * fRandom = fopen("/dev/urandom", "r");

	// We will need 3120 bytes of random data to populate the table
	if (!fread(zTable, 1, sizeof(zTable), fRandom) == sizeof(zTable))
	{
		printf("FATAL ERROR: fread() did not return sizeof(zTable) bytes from " 
				   "/dev/urandom\n");
		exit(EXIT_FAILURE);
	}

	if (!fread(&blackOnMove, sizeof(blackOnMove), 1, fRandom))
	{
		printf("FATAL ERROR: fread() did not return sizeof(blackOnMove) bytes from " 
				   "/dev/random\n");
		exit(EXIT_FAILURE);
	}
	
	if (!fread(&whiteOnMove, sizeof(whiteOnMove), 1, fRandom))
	{
		printf("FATAL ERROR: fread() did not return sizeof(whiteOnMove) bytes from " 
				   "/dev/random\n");
		exit(EXIT_FAILURE);
	}

	return;
}

// This method calculates a hash value for the board pointed to by pBoard.
unsigned long long int ZobristTable::hash(board * pBoard)
{
	unsigned long long hash = 0;
	unsigned int position = A6; //highest order position on bit board
	int i = 0; 
	int j = 0;
	for (i = 0; i < 30; i++)
	{
		j = findPiece(pBoard, position);
		hash = hash + zTable[i][j];
		position = position >> 1;
	}

	return hash;
}

unsigned long long ZobristTable::newHash(board * pBoard, unsigned int inTo, 
																		  	 unsigned int inFrom, PIECES piece,
																				 PIECES capturedPiece, 
																				 unsigned long long oldHash)
{
	int from = lookupPosition(inFrom);
	int to = lookupPosition(inTo);
	return (oldHash ^ zTable[from][piece] ^ zTable[from][BLANK] ^ 
			    zTable[to][capturedPiece] ^ zTable[to][piece] ^ 
					blackOnMove ^ whiteOnMove);
}

//this method takes a bit board and calculates which index in the array 
//to use to retrive it
int ZobristTable::lookupPosition(unsigned int mask)
{
  if (mask == A6)
    return 0;    
  else if (mask == B6)
    return 1;    
  else if (mask == C6)
    return 2;
  else if (mask == D6)
    return 3;    
  else if (mask == E6)
    return 4; 
  else if (mask == A5)
    return 5;
  else if (mask == B5)
    return 6; 
  else if (mask == C5)
    return 7;
  else if (mask == D5)
    return 8; 
  else if (mask == E5)
    return 9; 
  else if (mask == A4)
    return 10; 
  else if (mask == B4)
    return 11; 
  else if (mask == C4)
    return 12; 
  else if (mask == D4)
    return 13; 
  else if (mask == E4)
    return 14; 
  else if (mask == A3)
    return 15; 
  else if (mask == B3)
    return 16;
  else if (mask == C3)
    return 17;  
  else if (mask == D3)
    return 18; 
  else if (mask == E3)
    return 19; 
  else if (mask == A2)
    return 20; 
  else if (mask == B2)
    return 21; 
  else if (mask == C2)
    return 22; 
  else if (mask == D2)
    return 23; 
  else if (mask == E2)
    return 24; 
  else if (mask == A1)
    return 25; 
  else if (mask == B1)
    return 26; 
  else if (mask == C1)
    return 27; 
  else if (mask == D1)
    return 28; 
  else if (mask == E1)
    return 29; 	
	else
	{
		printf("Error in ZobristTable::lookupPosition\n");
		exit(EXIT_FAILURE);
	}
}

